package com.uc.sdk.g3.handler;

import com.uc.sdk.g3.CMD;
import com.uc.sdk.g3.G3FileUtil;
import com.uc.sdk.g3.IG3Watcher;
import com.uc.sdk.g3.vo.FileVo;
import com.uc.sdk.g3.vo.G3Content;
import com.uc.sdk.utils.NumberUtil;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * 协议转换内容
 */
public class G3ReadHandler extends ByteToMessageDecoder {
    private static final Logger LOGGER = LoggerFactory.getLogger(G3ReadHandler.class);
    IG3Watcher ig3Watcher;

    public G3ReadHandler(IG3Watcher ig3Watcher) {
        this.ig3Watcher = ig3Watcher;
    }

    /**
     * <pre>
     * 协议开始的标准head_data，int类型，占据2个字节.
     * </pre>
     */
    public final int BASE_LENGTH = 4;

    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        //判断缓冲区是否可读
        if (!byteBuf.isReadable()) {
            byteBuf.resetReaderIndex();
            return;
        }
        // 可读长度必须大于基本长度
        if(byteBuf.readableBytes() >= BASE_LENGTH){
            // 防止socket字节流攻击
            // 防止，客户端传来的数据过大
//            if (byteBuf.readableBytes() > 2048) {
//                byteBuf.skipBytes(byteBuf.readableBytes());
//            }
            // 记录包头开始的index
            int beginReader = 0;
            while(true){
                // 获取包头开始的index
                beginReader = byteBuf.readerIndex();
                // 标记包头开始的index
                byteBuf.markReaderIndex();
                byte[] head = new byte[BASE_LENGTH];
                byteBuf.readBytes(head);
                //读到协议头，结束循环
                if(Arrays.equals(head, CMD.HEADER)){
                    break;
                }
                byteBuf.resetReaderIndex();
            }
            if(byteBuf.readableBytes() < 4){
                byteBuf.readerIndex(beginReader);
                return;
            }
            byte[] lengthArr = new byte[4];
            byteBuf.readBytes(lengthArr);
            int xor = 0;
            for (byte b : lengthArr) {
                xor ^= b;
            }
            int length = NumberUtil.byte4ToInt(lengthArr);
//            System.out.println("length:{}" + length);
            if(byteBuf.readableBytes() < 1){
                byteBuf.readerIndex(beginReader);
                return;
            }
            int code = byteBuf.readByte();
            xor ^= code;
            //获取车型数据
            if(code == 0x08){
                if(byteBuf.readableBytes() >= length + 1){
                    byte[] content = new byte[length];
                    byteBuf.readBytes(content);
                    for (byte b : content) {
                        xor ^= b;
                    }
                    //获取校验位
                    byte xorPos = byteBuf.readByte();
                    if(xorPos == xor){
                        String str = new String(content);
                        int xmlPos = str.indexOf("</xml>");
                        String xml = str.substring(0,xmlPos) + "</xml>";
                        Document doc = DocumentHelper.parseText(xml);
                        Element root = doc.getRootElement();
                        List<FileVo> files = new ArrayList<>();
                        //获取文件及大小，最多支持八个
                        for (int i = 0; i < 8; i++) {
                            Element file = root.element("FILE"+i);
                            if(file == null){
                                break;
                            }
                            String fileName = file.getTextTrim();
                            Element sizeEle = root.element("SIZE"+ i);
                            int size = Integer.parseInt(sizeEle.getTextTrim());
                            FileVo vo = new FileVo();
                            vo.setFileName(fileName);
                            vo.setSize(size);
                            files.add(vo);
                        }
                        //获取到G3数据
                        G3Content g3Content = G3FileUtil.make(files,content);
                        ig3Watcher.execute(g3Content);
                    }
                }else{
                    byteBuf.readerIndex(beginReader);
                    return;
                }
            }
            else{
                byteBuf.readBytes(length + 1);
            }
        }
    }
}
